package com.bt7274.service.impl;

import com.bt7274.enums.PermissionGroupEnum;
import com.bt7274.mapper.UserExpMapper;
import com.bt7274.mapper.UserMapper;
import com.bt7274.pojo.UserExp;
import com.bt7274.service.UserExpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @BelongsProject: bt7274-back
 * @BelongsPackage: com.bt7274.service.impl
 * @Author: Galland
 * @CreateTime: 2025-05-17
 * @Description: TODO
 * @Version: 1.0
 */
@Slf4j
@Service
public class UserExpServiceImpl implements UserExpService {

    @Autowired
    private UserExpMapper userExpMapper;

    @Autowired
    private UserMapper userMapper;

    @Override
    public boolean initUserExp(String userId){
        return userExpMapper.initUserExp(userId) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUploadDownload(String userId, Long uploadedDelta, Long downloadedDelta) {
        boolean success = userExpMapper.updateUploadDownload(userId, uploadedDelta, downloadedDelta) > 0;
        if (success) {
            //更新完上传下载量后重新计算分享
            recalculateRatio(userId);
        }
        return success;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateExperience(String userId, Integer experienceDelta){
        boolean success = userExpMapper.updateExperience(userId, experienceDelta) > 0;
        if (success) {
            //经验值更新后检查是否需要升级
            autoUpgradeUserLevel(userId);
        }
        return success;
    }

    @Override
    public boolean updateBt(String userId, Integer btDelta){
        return userExpMapper.updateBt(userId, btDelta) > 0;
    }

    @Override
    public boolean hasSufficientBt(String userId, Integer amount){
        UserExp userExp = userExpMapper.selectById(userId);
        return userExp != null && userExp.getBt() >= amount;
    }

    @Override
    public boolean recalculateRatio(String userId) {
        return userExpMapper.recalculateRatio(userId) > 0;
    }

    @Override
    public Integer calculatePermissionGroup(Integer experience){
        //根据经验区间计算权限组
        if (experience < 100) {
            return PermissionGroupEnum.GRADUATE.getCode(); //毕业生
        }else if (experience < 500) {
            return PermissionGroupEnum.JUNIOR_DRIVER.getCode();
        }else if (experience < 2000) {
            return PermissionGroupEnum.QUALIFIED_DRIVER.getCode(); // 合格铁驭
        } else if (experience < 5000) {
            return PermissionGroupEnum.FAMOUS_DRIVER.getCode(); // 知名铁驭
        } else if (experience < 8000) {
            return PermissionGroupEnum.GLORY_DRIVER.getCode(); // 荣耀铁驭
        } else if (experience < 12000) {
            return PermissionGroupEnum.LEGENDARY_DRIVER.getCode(); // 传奇铁驭
        } else {
            return PermissionGroupEnum.BT_SUPREME.getCode(); // BT至尊
        }
    }

    @Override
    public UserExp getUserExp(String userId) {
        return userExpMapper.selectById(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean autoUpgradeUserLevel(String userId) {
        UserExp userExp = userExpMapper.selectById(userId);
        if (userExp == null) {
            return false;
        }

        Integer newPermissionGroup = calculatePermissionGroup(userExp.getExperience());

        //更新用户权限组
        return userMapper.updatePermissionGroup(userId, newPermissionGroup) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean rewardForSeed(String userId, Long torrentSize) {
        // 发种奖励：+10BT币 + 经验值（根据种子大小）
        boolean btSuccess = updateBt(userId, 10);

        // 根据种子大小计算经验值增量（每GB增加1经验值）
        int experienceGain = (int) (torrentSize / (1024 * 1024 * 1024));
        experienceGain = Math.max(1, experienceGain); // 至少增加1经验值
        boolean expSuccess = updateExperience(userId, experienceGain);

        log.info("用户 {} 发种获得奖励：{}BT币，{}经验值", userId, 10, experienceGain);
        return btSuccess && expSuccess;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean rewardForSeeding(String userId, Long torrentSize, Integer seedingHours) {
        // 保种奖励：根据种子大小和保种时长计算BT币
        // 计算公式：基础奖励 + (种子大小/GB * 保种小时数 / 24)
        int baseBt = 10;
        double sizeInGB = torrentSize / (1024.0 * 1024.0 * 1024.0);
        int sizeBt = (int) Math.min(sizeInGB * seedingHours / 24, 300); // 最多300BT
        int totalBt = baseBt + sizeBt;

        boolean btSuccess = updateBt(userId, totalBt);

        // 保种也给予少量经验值
        int experienceGain = Math.max(1, seedingHours / 24);
        boolean expSuccess = updateExperience(userId, experienceGain);

        log.info("用户 {} 保种获得奖励：{}BT币，{}经验值", userId, totalBt, experienceGain);
        return btSuccess && expSuccess;
    }

    @Override
    public UserExp createOrUpdate(UserExp userExp) {
        if(userExp.getId() == null){
            userExpMapper.insert(userExp);
        }else{
            userExpMapper.updateById(userExp);
        }
        return userExp;
    }

    /**
     * 计算下载付费种子所需花费的 BT 币个数
     * @param torrentSize 种子的大小，单位为字节
     * @return 花费的 BT 币个数，范围在 10 到 500 之间
     */
    @Override
    public int calculateDownloadCost(Long torrentSize) {
        // 每 GB 收取 20 BT 币
        double sizeInGB = torrentSize / (1024.0 * 1024.0 * 1024.0);
        int cost = (int) (sizeInGB * 20);
        // 确保价格不低于 10 BT 且不高于 500 BT
        return Math.min(Math.max(cost, 10), 500);
    }
}
